import React from 'react';
import './index.scss';
import { Form, Input, Button, message, Image, Tabs, Modal } from 'antd';
import { UserOutlined, KeyOutlined, SafetyOutlined, PhoneFilled } from '@ant-design/icons';
import {
  casLogin,
  casLoginWithPhone,
  casRetrievePassword,
  getCasUserInfo,
  getCodeImg,
  sendSmsValidateCode,
  fenQuanUserId,
} from 'admin/servers/servers';
import { v4 as uuidv4 } from 'uuid';
import { FormInstance } from 'antd/lib/form';
import { AES, enc, mode, pad } from 'crypto-js';
import {
  setSystemConfigAsynic,
  setToken,
  setUniqueToken,
  setEncryptToken,
  setUserInfoLater,
  setLoginInfo,
  setUserInfo,
} from 'store/root/action';
import { connect } from 'react-redux';
import { JSONObject } from '../../schema/common';
import { RouteConfigComponentProps } from 'react-router-config';
import { logoutSys } from 'utils';
import { debounce } from 'lodash';
import { validateUserPwdRule } from 'utils/modules/validateUserPwdRule';

/**
 * 登录模块维护的state
 */
interface LoginState {
  // 登录按钮状态
  loading: boolean;
  // 当前验证码随机uuid
  codeId: string;
  // 验证码图片
  codeImg: string;
  // 是否展示
  show: boolean;
  // 检查图形验证码是否必填
  checkCode: boolean;
  // 检查短信验证码是否必填
  checkSms: boolean;
  // 验证码发送中
  smsLoading: boolean;
  // 短信验证码获取按钮状态-1-获取验证码，2-重发，0-重发倒计时（禁用状态）
  smsBtnActive: 1 | 2 | 0;
  // 倒计时-60秒
  count: number;
  showSmsCodeCheck: boolean; // 是否展示短信验证码
  activeTab: string;
  // 新增忘记密码modal的状态
  forgotPasswordVisible: boolean;
  forgotPasswordLoading: boolean;

  smsRetrieveLoading: boolean;
  smsRetrieveBtnActive: 1 | 2 | 0;
  smsRetrieveCount: number;
}

/**
 * 系统登录页-最新-唯一-合并版
 * 包含：短信验证码登录方式和普通登录方式
 */
class LoginSms extends React.Component<{}, LoginState> {
  // 登录form的表单引用
  form: React.RefObject<FormInstance>;
  smsForm: React.RefObject<FormInstance>;
  forgotPasswordForm: React.RefObject<FormInstance>;

  constructor(prop: {}) {
    super(prop);
    this.form = React.createRef();
    this.smsForm = React.createRef();
    this.forgotPasswordForm = React.createRef();
    this.state = {
      loading: false,
      codeId: uuidv4(),
      codeImg: '',
      show: false,
      checkCode: true,
      checkSms: true,
      smsLoading: false,
      smsBtnActive: 1,
      count: 0,
      showSmsCodeCheck: false,
      activeTab: 'password', // 新增：默认显示密码登录tab
      forgotPasswordVisible: false,
      forgotPasswordLoading: false,
      smsRetrieveLoading: false,
      smsRetrieveBtnActive: 1,
      smsRetrieveCount: 0,
    };
  }

  componentDidMount() {
    this.checkToken();
  }
  componentWillUnmount = () => {
    this.setState = (state, callback) => {
      return;
    };
  };

  private handleSmsRetrieveCode = debounce(() => {
    (this.forgotPasswordForm.current as FormInstance)
      .validateFields(['phone'])
      .then(values => {
        this.setState({
          smsRetrieveLoading: true,
        });
        return sendSmsValidateCode({
          phone: values.phone,
          type: 11,
        });
      })
      .then(res => {
        message.warning('短信验证码已发送');
        this.setState({
          smsRetrieveBtnActive: 0,
          smsRetrieveCount: 60,
        });
        const time = setInterval(() => {
          if (this.state.smsRetrieveCount <= 0) {
            clearInterval(time);
            console.log('重发倒计时结束', this.state.smsRetrieveCount);
            this.setState({
              smsRetrieveBtnActive: 2,
            });
            return;
          }
          this.setState({ smsRetrieveCount: this.state.smsRetrieveCount - 1 });
        }, 1000);
      })
      .catch(err => {
        console.error(`系统异常: ${JSON.stringify(err)}`);
        this.setState({
          smsRetrieveBtnActive: 1,
        });
      })
      .finally(() => {
        this.setState({
          smsRetrieveLoading: false,
        });
      });
  }, 500);

  /**获取短信验证码 */
  private handleSmsCode = debounce(() => {
    (this.smsForm.current as FormInstance)
      .validateFields(['phone'])
      .then(values => {
        this.setState({
          smsLoading: true,
        });
        return sendSmsValidateCode({
          phone: values.phone,
          type: 12,
        });
      })
      .then(res => {
        message.warning('短信验证码已发送');
        this.setState({
          smsBtnActive: 0,
          count: 60,
        });
        const time = setInterval(() => {
          if (this.state.count <= 0) {
            clearInterval(time);
            console.log('重发倒计时结束', this.state.count);
            this.setState({
              smsBtnActive: 2,
            });
            return;
          }
          this.setState({ count: this.state.count - 1 });
        }, 1000);
      })
      .catch(err => {
        console.error(`系统异常: ${JSON.stringify(err)}`);
        this.setState({
          smsBtnActive: 1,
        });
      })
      .finally(() => {
        this.setState({
          smsLoading: false,
        });
      });
  }, 500);

  private onSubmitSms = debounce(() => {
    this.smsForm.current
      .validateFields()
      .then(smsValues => {
        this.setState({
          loading: true,
        });
        return casLoginWithPhone({
          phone: smsValues.phone,
          verificationCode: smsValues.verificationCode,
        });
      })
      .then(({ data }) => {
        const history = (this.props as any).history;
        // (this.props as JSONObject).setToken(data.uniqueToken);
        (this.props as JSONObject).setUniqueToken(data.uniqueToken);
        (this.props as JSONObject).setEncryptToken(data.encryptToken);
        (this.props as JSONObject).setLoginInfo({ ...data });
        message.success('登录成功');
        history.push('/webapp/cas/abilities');
      })
      .finally(() => {
        this.setState({
          loading: false,
        });
      });
  }, 500);

  /**提交信息登录-普通登录 */
  private onSubmit = debounce(() => {
    (this.form.current as FormInstance).validateFields().then(async values => {
      this.setState({
        loading: true,
      });
      const AESKEY = enc.Utf8.parse('1111111111111111');
      const AESIV = enc.Utf8.parse('2222222222222222');
      const password = AES.encrypt(values.password || '', AESKEY, {
        iv: AESIV,
        mode: mode.CBC,
        padding: pad.ZeroPadding,
      }).toString();
      try {
        const { data } = await casLogin({
          username: values.username,
          password,
          verificationCode: values.codeWord,
        });
        const history = (this.props as any).history;
        // (this.props as JSONObject).setToken(data.uniqueToken);
        (this.props as JSONObject).setUniqueToken(data.uniqueToken);
        (this.props as JSONObject).setEncryptToken(data.encryptToken);
        (this.props as JSONObject).setLoginInfo({ ...data });
        // 分权ID换行短ID
        fenQuanUserId(data.id).then(res => {
          (this.props as JSONObject).setUserInfo({ userId: res.data });
        });
        message.success('登录成功');
        history.push('/webapp/cas/abilities');
      } catch (error) {
        console.error(`系统异常: ${JSON.stringify(error)}`);
        this.onCodeChange();
      }
      this.setState({
        loading: false,
      });
    });
  }, 500);

  /**检测token是否有效 */
  private checkToken = () => {
    // 如果token有效，直接跳转，无需重新登录
    const history = (this.props as any).history;
    const { token, loginInfo } = this.props as any;
    if (token && token !== '') {
      // token有值，可能是其他页面跳转到登录页面，带有token。
      // 需要请求接口验证token是否有效
      getCasUserInfo({ username: loginInfo.username })
        .then(res => {
          // token有效
          history.push('/webapp');
        })
        .catch(err => {
          // token无效
          if (process.env.REACT_APP_LOGIN_NO_CHECK != '1') {
            logoutSys();
          }
          this.showLoginBox();
        });
    } else {
      // token无值
      this.showLoginBox();
    }
  };

  /**显示登录区域，切换验证码，聚焦输入框 */
  private showLoginBox = () => {
    this.setState(
      {
        show: true,
      },
      () => {
        document.getElementById('username')?.focus();
        this.onCodeChange();
      }
    );
  };

  private onCodeChange = debounce(() => {
    getCodeImg().then(res => {
      this.setState({
        codeImg: URL.createObjectURL(res),
      });
    });
  }, 500);

  private handleForgotPassword = debounce(() => {
    (this.forgotPasswordForm.current as FormInstance)
      .validateFields()
      .then(values => {
        this.setState({ forgotPasswordLoading: true });
        return casRetrievePassword({
          phone: values.phone,
          validateCode: values.validateCode,
          password: values.newPassword,
          confirmPassword: values.confirmPassword,
        });
      })
      .then(() => {
        message.success('密码重置成功');
        this.setState({ forgotPasswordVisible: false });
        (this.forgotPasswordForm.current as FormInstance).resetFields();
      })
      .catch(err => {
        console.error(`系统异常: ${JSON.stringify(err)}`);
      })
      .finally(() => {
        this.setState({ forgotPasswordLoading: false });
      });
  }, 500);

  private showForgotPasswordModal = () => {
    this.setState({ forgotPasswordVisible: true });
  };

  private hideForgotPasswordModal = () => {
    this.setState({ forgotPasswordVisible: false });
  };

  handleTabChange = (activeKey: string) => {
    this.setState({ activeTab: activeKey });
    // 切换tab时重置表单
    this.form.current?.resetFields();
    this.smsForm.current?.resetFields();
  };

  validatePassword = (_: any, value: string) => {
    const Fn = validateUserPwdRule;
    const { code, msg } = Fn.checkPassword(null, value);
    return code ? Promise.reject(msg) : Promise.resolve();
  };

  render() {
    const {
      show,
      loading,
      codeImg,
      checkSms,
      smsLoading,
      smsBtnActive,
      count,
      forgotPasswordVisible,
      forgotPasswordLoading,
      smsRetrieveLoading,
      smsRetrieveBtnActive,
      smsRetrieveCount,
    } = this.state;
    const { systemConfig } = this.props as JSONObject;
    const { form, smsForm, forgotPasswordForm } = this;

    return (
      <div className="page-login">
        <div className={show ? 'loginBox show' : 'loginBox'}>
          <div className="page-login-title">
            {systemConfig?.systemName || '西安市综合短信发布平台'}
          </div>
          <Tabs activeKey={this.state.activeTab} onChange={this.handleTabChange} centered>
            <Tabs.TabPane tab={<div style={{ fontSize: 18 }}>密码登录</div>} key="password">
              <Form ref={form}>
                <Form.Item
                  name="username"
                  rules={[
                    { max: 15, message: '最大长度为15位字符' },
                    {
                      required: true,
                      whitespace: true,
                      message: '请输入账号',
                    },
                  ]}
                  getValueFromEvent={event => {
                    return event.target.value.replace(/\s+/g, '');
                  }}
                >
                  <Input
                    prefix={<UserOutlined style={{ fontSize: 13 }} />}
                    size="large"
                    id="username"
                    placeholder="请输入账号"
                    onPressEnter={this.onSubmit}
                  />
                </Form.Item>
                <Form.Item
                  name="password"
                  rules={[{ required: true, message: '请输入密码' }]}
                  getValueFromEvent={event => {
                    return event.target.value.replace(/\s+/g, '');
                  }}
                >
                  <Input
                    prefix={<KeyOutlined style={{ fontSize: 13 }} />}
                    size="large"
                    id="password"
                    type="password"
                    placeholder="请输入密码"
                    onPressEnter={this.onSubmit}
                  />
                </Form.Item>

                <Form.Item style={{ marginBottom: 5 }}>
                  <Form.Item
                    name="codeWord"
                    noStyle
                    rules={[{ required: true, message: '请输入图形验证码' }]}
                    getValueFromEvent={event => {
                      return event.target.value.replace(/[^a-zA-Z0-9]+/g, '').slice(0, 4);
                    }}
                  >
                    <Input
                      prefix={<SafetyOutlined style={{ fontSize: 13 }} />}
                      style={{ width: '200px' }}
                      size="large"
                      id="codeWord"
                      maxLength={4}
                      placeholder="图形验证码"
                      onPressEnter={this.onSubmit}
                    />
                  </Form.Item>
                  <Image
                    alt="图形验证码"
                    src={codeImg}
                    height={40}
                    width={140}
                    preview={false}
                    onClick={this.onCodeChange}
                    className="login-code"
                  />
                </Form.Item>
                <Form.Item style={{ marginBottom: 5 }}>
                  <div style={{ width: '100%' }}>
                    <a
                      href="javascript:;"
                      style={{
                        float: 'right',
                        color: '#1890ff',
                        fontSize: '14px',
                        textDecoration: 'none',
                      }}
                      onClick={this.showForgotPasswordModal}
                    >
                      忘记密码
                    </a>
                  </div>
                </Form.Item>

                <div style={{ lineHeight: '40px', textAlign: 'center' }}>
                  <Button
                    className="submit-btn"
                    size="large"
                    type="primary"
                    loading={loading}
                    onClick={this.onSubmit}
                  >
                    {loading ? '请稍后' : '登录'}
                  </Button>
                </div>
              </Form>
            </Tabs.TabPane>
            <Tabs.TabPane tab={<div style={{ fontSize: 18 }}>短信登录</div>} key="sms">
              <Form ref={smsForm}>
                <Form.Item
                  name="phone"
                  rules={[
                    {
                      required: true,
                      validator: (rule, value) => {
                        if (!value) {
                          return Promise.reject('请输入短信验证码');
                        }
                        return /^1[3|4|5|6|7|8|9][0-9]\d{8}$/.test(value.toString())
                          ? Promise.resolve()
                          : Promise.reject('请输入正确格式的手机号');
                      },
                    },
                  ]}
                  getValueFromEvent={event => {
                    return event.target.value.replace(/\s+/g, '');
                  }}
                >
                  <Input
                    prefix={<PhoneFilled style={{ fontSize: 13 }} />}
                    size="large"
                    placeholder="请输入手机号"
                  />
                </Form.Item>
                <Form.Item>
                  <Form.Item
                    name="verificationCode"
                    noStyle
                    rules={[{ required: checkSms, message: '请输入短信验证码' }]}
                    getValueFromEvent={event => {
                      return event.target.value.replace(/[^a-zA-Z0-9]+/g, '').slice(0, 6);
                    }}
                  >
                    <Input
                      prefix={<SafetyOutlined style={{ fontSize: 13 }} />}
                      style={{ width: '200px' }}
                      size="large"
                      maxLength={6}
                      placeholder="短信验证码"
                    />
                  </Form.Item>
                  <Button
                    size="large"
                    style={{ width: '140px' }}
                    type="primary"
                    loading={smsLoading}
                    disabled={!smsBtnActive}
                    onClick={this.handleSmsCode}
                  >
                    {smsBtnActive
                      ? smsBtnActive > 1
                        ? '重发'
                        : '获取验证码'
                      : '重发(' + count + 's)'}
                  </Button>
                </Form.Item>
                <div style={{ lineHeight: '40px', textAlign: 'center' }}>
                  <Button
                    size="large"
                    type="primary"
                    loading={loading}
                    onClick={this.onSubmitSms}
                    style={{ width: 270 }}
                  >
                    {loading ? '请稍后' : '登录'}
                  </Button>
                </div>
              </Form>
            </Tabs.TabPane>
          </Tabs>
        </div>
        <Modal
          title="忘记密码"
          visible={forgotPasswordVisible}
          onCancel={this.hideForgotPasswordModal}
          width={400}
          maskClosable={false}
          destroyOnClose={true}
          footer={null}
        >
          <Form ref={forgotPasswordForm}>
            <Form.Item
              name="phone"
              rules={[
                {
                  required: true,
                  validator: (rule, value) => {
                    if (!value) {
                      return Promise.reject('请输入手机号');
                    }
                    return /^1[3|4|5|6|7|8|9][0-9]\d{8}$/.test(value.toString())
                      ? Promise.resolve()
                      : Promise.reject('请输入正确格式的手机号');
                  },
                },
              ]}
            >
              <Input prefix={<PhoneFilled />} placeholder="请输入手机号" />
            </Form.Item>

            <Form.Item>
              <Form.Item
                name="validateCode"
                noStyle
                rules={[{ required: true, message: '请输入短信验证码' }]}
              >
                <Input
                  prefix={<SafetyOutlined />}
                  style={{ width: '200px' }}
                  placeholder="短信验证码"
                />
              </Form.Item>
              <Button
                style={{ width: '140px' }}
                type="primary"
                loading={smsRetrieveLoading}
                disabled={!smsRetrieveBtnActive}
                onClick={this.handleSmsRetrieveCode}
              >
                {smsRetrieveBtnActive
                  ? smsRetrieveBtnActive > 1
                    ? '重发'
                    : '获取验证码'
                  : '重发(' + smsRetrieveCount + 's)'}
              </Button>
            </Form.Item>

            <Form.Item
              name="newPassword"
              tooltip="8位以上字符，需包含大写字母、小写字母、数字和特殊字符中的三类"
              rules={[
                { required: true, message: '请输入密码' },
                { validator: this.validatePassword },
              ]}
            >
              <Input.Password prefix={<KeyOutlined />} placeholder="请输入新密码" />
            </Form.Item>

            <Form.Item
              name="confirmPassword"
              dependencies={['newPassword']}
              rules={[
                { required: true, message: '请确认新密码' },
                ({ getFieldValue }) => ({
                  validator(_, value) {
                    if (!value || getFieldValue('newPassword') === value) {
                      return Promise.resolve();
                    }
                    return Promise.reject('两次输入的密码不一致');
                  },
                }),
              ]}
            >
              <Input.Password prefix={<KeyOutlined />} placeholder="请确认新密码" />
            </Form.Item>

            <Form.Item>
              <Button
                type="primary"
                block
                loading={forgotPasswordLoading}
                onClick={this.handleForgotPassword}
              >
                重置密码
              </Button>
            </Form.Item>
          </Form>
        </Modal>
      </div>
    );
  }
}
// state 注入props
const mapStateToProps = (state: JSONObject) => {
  return {
    systemConfig: state.systemConfig,
    token: state.token,
    loginInfo: state.loginInfo,
  };
};
// action 注入props
const mapDispatchToProps = {
  setSystemConfigAsynic,
  setToken,
  setUniqueToken,
  setEncryptToken,
  setUserInfo,
  setLoginInfo,
  setUserInfoLater,
};

export default connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true })(
  LoginSms
) as React.ComponentType<RouteConfigComponentProps<any>>;
